<template>
  <div class="threshold-wrap">
    <el-form class="threshold-list" ref="form">
      <span v-for="(v, vIndex) in thresholdList" :key="v.id">
        <el-form-item prop="symbol" class="symbol" v-if="v.symbol !== 'to'">
          <el-select v-model="v.symbol" size="mini" placeholder="">
            <el-option
              v-for="s in symbolList"
              :key="s.id"
              :label="s.label"
              :value="s.id"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item
          :prop="v.symbol !== 'to' ? 'indexValueList' : ''"
          class="indexValueList"
        >
          <template v-if="v.symbol === 'to'">
            <template v-if="v.dataType === 1">
              <el-select v-model="v.contain1" size="mini" placeholder="">
                <el-option
                  v-for="s in toList"
                  :key="s.id"
                  :label="s.label"
                  :value="s.id"
                >
                </el-option>
              </el-select>
              <el-date-picker
                v-model="v.containVal1"
                type="date"
                size="mini"
                :clearable="false"
                placeholder=""
                format="yyyy-MM-dd"
                value-format="timestamp"
              >
              </el-date-picker>
              ~
              <el-select v-model="v.contain2" size="mini" placeholder="">
                <el-option
                  v-for="s in toList"
                  :key="s.id"
                  :label="s.label"
                  :value="s.id"
                >
                </el-option>
              </el-select>
              <el-date-picker
                v-model="v.containVal2"
                type="date"
                size="mini"
                :clearable="false"
                placeholder=""
                format="yyyy-MM-dd"
                value-format="timestamp"
              >
              </el-date-picker>
            </template>
            <template v-else-if="v.dataType === 2">
              <el-select v-model="v.contain1" size="mini" placeholder="">
                <el-option
                  v-for="s in toList"
                  :key="s.id"
                  :label="s.label"
                  :value="s.id"
                >
                </el-option>
              </el-select>
              <el-input
                v-model="v.containVal1"
                size="mini"
                placeholder=""
                type="number"
                @input="handleInput($event, vIndex, 'containVal1')"
              ></el-input>
              ~
              <el-select v-model="v.contain2" size="mini" placeholder="">
                <el-option
                  v-for="s in toList"
                  :key="s.id"
                  :label="s.label"
                  :value="s.id"
                >
                </el-option>
              </el-select>
              <el-input
                v-model="v.containVal2"
                size="mini"
                placeholder=""
                type="number"
                @input="handleInput($event, vIndex, 'containVal2')"
              ></el-input>
            </template>
          </template>
          <template v-else>
            <template v-if="v.dataType === 1">
              <el-date-picker
                v-model="v.indexValueList"
                type="date"
                size="mini"
                :clearable="false"
                placeholder=""
                format="yyyy-MM-dd"
                value-format="timestamp"
              >
              </el-date-picker>
            </template>
            <template v-else-if="v.dataType === 2">
              <el-input
                v-model="v.indexValueList"
                size="mini"
                placeholder=""
                type="number"
                @input="handleInput($event, vIndex)"
              ></el-input>
            </template>
          </template>
        </el-form-item>

        <el-form-item prop="score" class="score">
          <el-input-number
            v-model="v.score"
            size="mini"
            type="number"
            :min="0"
            :max="100"
          ></el-input-number>
        </el-form-item>

        <el-form-item>
          <i class="el-icon-delete" @click="del(vIndex)"></i>
        </el-form-item>
      </span>

      <el-button icon="el-icon-plus" size="mini" @click="add">添加</el-button>
    </el-form>

    <div class="footer">
      <el-button
        type="primary"
        size="mini"
        @click="handleSave"
        >保存</el-button
      >
    </div>
  </div>
</template>

<script>
import { symbolList, toList, toListMap } from '@/utils/constant'
import { isBlank } from '@/utils/utils'

export default {
  name: 'Threshold',
  components: {},
  props: {},
  data() {
    return {
      thresholdList: [],
      symbolList,
      toList,
      toListMap,
    }
  },
  watch: {},
  computed: {},
  created() {},
  mounted() {},
  methods: {
    add() {
      this.thresholdList = this.thresholdList.concat({
        dataType: 2,
        symbol: null,
        indexValueList: null,
        score: null,
        contain1: null,
        contain2: null,
        containVal1: null,
        containVal2: null,
      })
    },
    del(vIndex) {
      this.thresholdList = this.thresholdList.filter(
        (element, eIndex) => vIndex !== eIndex
      );
    },
    handleInput(value, vIndex, type) {
      this.thresholdList = this.thresholdList.map((item, index) => {
        if(index === vIndex) {
          if(item.symbol !== 'to') {
             return {
              ...item, 
              indexValueList: value.startsWith('.') ? '0' + value : value,
            }
          }else {
            if(type === 'containVal1') {
              return {
                ...item, 
                containVal1: value.startsWith('.') ? '0' + value : value,
              }
            }else if(type === 'containVal2') {
              return {
                ...item, 
                containVal2: value.startsWith('.') ? '0' + value : value,
              }
            }
          }
        }
        return item
      })
    },
    // 将关系符转换为区间
    toInterval(obj) {
      let start, end
      const epsilon = 1e-9    // 1e-9表示浮点数，具体是0.000000001，一个很小的可以忽略不计的数
      // symbol='to'时，indexValueList是数组，存两个数字，否则就是string，一个数字
      const value = obj.symbol !== 'to' && parseFloat(obj.indexValueList)
      switch(obj.symbol) {
        case 'gt':
          // >
          start = value + epsilon
          end = Infinity
          break
        case 'lt':
          // <
          start = -Infinity
          end = value - epsilon
          break
        case 'gte':
          // ≥
          start = value
          end = Infinity
          break
        case 'le':
          // ≤
          start = -Infinity
          end = value
          break
        case 'equ':
          // =
          return { point: value }
        case 'gt_lt':
          // (a, b)
          start = parseFloat(obj.indexValueList[0]) + epsilon
          end = parseFloat(obj.indexValueList[1]) - epsilon
          break
        case 'gt_le':
          // (a, b]
          start = parseFloat(obj.indexValueList[0]) + epsilon
          end = parseFloat(obj.indexValueList[1])
          break
        case 'gte_lt':
          // [a, b)
          start = parseFloat(obj.indexValueList[0])
          end = parseFloat(obj.indexValueList[1]) - epsilon
          break
        case 'gte_le':
          // [a, b]
          start = parseFloat(obj.indexValueList[0])
          end = parseFloat(obj.indexValueList[1])
          break
        // case 'ne':
        //   // ≠
        //   return { neqValue: value }
      }
   
      return { start, end }
    },
    // 校验是否重叠
    checkOverlap(a, b) {
      // 第一种情况：两条数据一个是区间，一个是=具体数据
      if((a.point !== undefined && b.start !== undefined && b.end !== undefined) || 
        (b.point !== undefined && a.start !== undefined && a.end !== undefined)) 
      {
        // 分两种情况：1、第一条数据是=，第二条数据是区间；2、第一条数据是区间，第二条数据是=
        if(a.point !== undefined && b.start !== undefined && b.end !== undefined) {
          return !(a.point < b.start || a.point>b.end)
        }
        if(a.start !== undefined && a.end !== undefined && b.point !== undefined) {
          return !(b.point < a.start || b.point > a.end)
        }
        return false    // 区间和=的没有重叠
      }else if(a.start !== undefined && a.end !== undefined && b.start !== undefined && b.end !== undefined) {
        // 第二种情况：两条数据都是区间
        return !(a.start > b.end || a.end < b.start)
      }else if(a.point !== undefined && b.point !== undefined) {
        // 第三种情况：两条数据都是=
        return a.point === b.point
      }
    },
    /**
     * 
     * @param int1 第一条数据
     * @param int2 第二条数据
     */
    check(int1, int2, i, j) {
      if(int1.point !== undefined && int2.start !== undefined && int2.end !== undefined) {
        if(this.checkOverlap({point: int1.point}, {start: int2.start, end: int2.end})) {
          return ` 第${i+1}行（= ${int1.point}）落在第${j+1}行的区间内\n`
        }
      }
      if(int1.start !== undefined && int1.end !== undefined && int2.point !== undefined) {
        if(this.checkOverlap({start: int1.start, end: int1.end}, {point: int2.point})) {
          return ` 第${j+1}行（= ${int2.point}）落在第${i+1}行的区间内\n`

        }
      }
      if(int1.start !== undefined && int1.end !== undefined && int2.start !== undefined && int2.end !== undefined) {
        if(this.checkOverlap({start: int1.start, end: int1.end}, {start: int2.start, end: int2.end})) {
          return ` 第${i+1}行和第${j+1}行有重叠\n`
        }
      }
      if(int1.point !== undefined && int2.point !== undefined) {
        if(int1.point === int2.point) {
          return ` 第${i+1}行（= ${int1.point}）和第${j+1}行（= ${int2.point}）有重复\n`
        }
      }
      return false
    },
    // 校验阈值，首先不能为空，其次：一行算一条数据，每个数据之间不能有重叠区间
    handleSave() {
      if(!this.thresholdList.length) {
        this.$message.error('请添加阈值')
        return
      }

      if(this.thresholdList && this.thresholdList.length>0) {
        const newlist = this.thresholdList.map(item => {
        if(item.symbol === 'to') {
            const foundTo = this.toListMap.find(v => JSON.stringify(v.label) === JSON.stringify([item.contain1, item.contain2]))
            const symbol = foundTo && foundTo.id
            return {
              symbol,
              indexValueList: [item.containVal1, item.containVal2],
              score: item.score,
            }
          } 
          return item
        })

        // 1、判空
        let info1 = []
        newlist.forEach((item, index) => {
          if(isBlank(item.symbol) || isBlank(item.indexValueList) || isBlank(item.score)) {
            info1.push(`第${index+1}行数据不完整\n`)
          }      
        })

        // 2、校验阈值重叠，thresholdList中不止两条数据，两两比较所有的数据
        const n = newlist.length
        let info2 = []
        for (let i = 0; i < n; i++) {
          const int1 = this.toInterval(newlist[i])   //将数据转换为区间
          for (let j = i + 1; j < n; j++) {
            const int2 = this.toInterval(newlist[j])
            // 如果重叠，将提示信息塞进info2数组中
            this.check(int1, int2, i, j) && info2.push(this.check(int1, int2, i, j))
          }
        }
        if(info1 && info1.length>0) {
          this.$message({
            message: info1.join(''),
            type: 'error',
            customClass: 'custom-message',
          })
        }else if(info2 && info2.length>0) {
          this.$message({
            message: info2.join(''),
            type: 'error',
            customClass: 'custom-message',
          })
        }else {
          this.$message.success('保存成功')
        }
      }
    }
  },
}
</script>

<style lang="scss" scoped>
.threshold-wrap {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;

  .threshold-list {
    width: 100%;
    flex: 1;

    &>span {
      display: flex;

      .indexValueList {
        ::v-deep .el-form-item__content {
          display: flex;
        }
      }

      .el-icon-delete {
        cursor: pointer;
        margin-left: 10px;
        color: #409eff;
      }
    }
  }
}
</style>

<style lang="scss">
.custom-message {
  white-space: pre-line; /* 使 \n 生效 */
  
  .el-message__content {
    line-height: 20px;
  }
}
</style>